﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="With_ModelBase.Silverlight.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the With_ModelBase type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.ComponentModel.Modelling
{
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Threading;
    using Windows.Input.Commands;

    public partial class With_ModelBase
    {
        [TestClass]
        public class When_command_integration_is_enabled : With_ModelBase<When_command_integration_is_enabled.TestModel>
        {
            #region Fields

            public int InvalidateCount;

            #endregion

            [TestInitialize]
            public void TestInitialize()
            {
                InvalidateCount = 0;
                CommandManager.RequerySuggested += OnCommandRequerySuggested;
                UIDispatcher.Current = Dispatcher.Synchronous;
            }

            [TestCleanup]
            public void TestCleanup()
            {
                CommandManager.RequerySuggested -= OnCommandRequerySuggested;
                UIDispatcher.Current = null;
            }

            private void OnCommandRequerySuggested(object sender, EventArgs e)
            {
                InvalidateCount++;
            }

            [TestMethod]
            public void Should_not_invalidate_commands_on_create()
            {
                Assert.AreEqual(0, InvalidateCount);
            }

            [TestMethod]
            public void If_property_is_changed_should_invalidate_commands()
            {
                Model.Value++;
                Assert.AreEqual(1, InvalidateCount);
                Model.Value++;
                Assert.AreEqual(2, InvalidateCount);
            }

            [TestMethod]
            public void If_property_is_not_changed_should_not_invalidate_commands()
            {
                Model.Value = 0;
                Assert.AreEqual(0, InvalidateCount);
            }

            [TestMethod]
            public void If_change_is_cancelled_should_not_invalidate_commands()
            {
                Model.Value = 11;
                Assert.AreEqual(0, Model.Value);
                Assert.AreEqual(0, InvalidateCount);
            }

            [TestMethod]
            public void Should_not_invalid_commands_until_suspend_scope_is_ended()
            {
                using (Model.NewSuspendNotify())
                {
                    Model.Value++;
                    Assert.AreEqual(0, InvalidateCount);
                }

                Assert.AreEqual(1, InvalidateCount);
            }

            #region Nested type: RestrictToRangeAttribute

            public class RestrictRangeAttribute : PropertyChangingAttribute
            {
                public RestrictRangeAttribute(int minimumValue, int maximumValue)
                {
                    MinimumValue = minimumValue;
                    MaximumValue = maximumValue;
                }

                public int MinimumValue { get; set; }
                public int MaximumValue { get; set; }

                public override bool OnChanging(object instance, MetaModelProperty property, object oldValue,
                                                ref object newValue)
                {
                    var typedNewValue = Convert.ToInt32(newValue);
                    return typedNewValue >= MinimumValue && typedNewValue <= MaximumValue;
                }
            }

            #endregion

            #region Nested type: TestModel

            public class TestModel : ModelBase
            {
                private int _value;

                [RestrictRange(0, 10)]
                public int Value
                {
                    get { return _value; }
                    set { SetProperty(ref _value, value, "Value"); }
                }
            }

            #endregion
        }
    }
}
